package Bot

import (
	"crypto/md5"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"time"
	"github.com/fatih/color"
	"bytes"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

const (
	md5url    = "http://222.186.59.77:30012/MD5.txt"
	//更新日志
	update_log = "http://222.186.59.77:30012/Update_log.txt"
	fileurl   = "http://222.186.59.77:30012/GoBox"
	localPath = "GoBox"
)
// UpdateGoBox 更新 GoBox 程序
func UpdateGoBox() error {
	//切换GoBox目录
	os.Chdir(GoBoxPath)
	md5str, err := downloadRemoteFile(md5url)
	if err != nil {
		//红色字体log打印
		color.Red("GoBox 更新失败：%s", err)
		time.Sleep(2 * time.Second)
		return err
	}

	if fileExists(localPath) {
		if localMd5, _ := localFileMD5(localPath); localMd5 == md5str {
			//绿色字体
			color.Green("GoBox 已经是最新版本...")
			time.Sleep(2 * time.Second)
			return nil
		}
	}
	//打印更新日志
	logfile, err := downloadRemoteFile(update_log)
	if err != nil {
		//红色字体log打印	
		color.Red("获取更新日志失败：%s", err)
		time.Sleep(2 * time.Second)
		return err
	}
	//打印更新日志
	//绿色字体
	//转换UTF_8，防止乱码 
	utf8Reader := transform.NewReader(bytes.NewReader([]byte(logfile)), simplifiedchinese.GBK.NewDecoder())
	utf8Logfile, err := ioutil.ReadAll(utf8Reader)
	if err != nil {
		// 错误处理
	}
	// 输出更新日志
	fmt.Println("新版本更新日志：")
	// fmt.Println(string(utf8Logfile))
	color.Green(string(utf8Logfile))
	fmt.Printf("是否更新？(y/n):")
	var confirm string
	fmt.Scanln(&confirm)
	if confirm != "y" {
		//黄色字体
		color.Yellow("已取消更新...")
		time.Sleep(1 * time.Second)
		return nil
	}

	if err := downloadAndVerifyFile(fileurl, localPath, md5str); err != nil {
		//红色字体
		color.Red("GoBox 更新失败：%s", err)
		//删除下载的文件
		tempPath := localPath + ".new"
		os.Remove(tempPath)
		time.Sleep(4 * time.Second)

		return err
	}
	//修改权限
	if err := os.Chmod(localPath, 0755); err != nil {
		// 红色字体
		color.Red("修改文件权限失败：%s", err)
		return err
	}
	fmt.Println("GoBox 更新成功,请重新启动....")
	time.Sleep(2 * time.Second)
	//返回字符串，用于判断是否更新成功
	os.Exit(0)
	return nil
}

func downloadRemoteFile(url string) (string, error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	return string(body), err
}

func downloadAndVerifyFile(url, filePath, md5sum string) error {
	tempPath := filePath + ".new"

	md5, err := downloadFile(url, tempPath)
	if err != nil {
		return err
	}

	if md5 != md5sum {
		return fmt.Errorf("文件和服务器不一致,校验失败,欢迎加入QQ群反馈:546537258")
	}

	return os.Rename(tempPath, filePath)
}

func downloadFile(url, filename string) (string, error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	file, err := os.Create(filename)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	_, err = io.Copy(io.MultiWriter(file, hash), resp.Body)
	return fmt.Sprintf("%x", hash.Sum(nil)), err
}

func localFileMD5(filePath string) (string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	_, err = io.Copy(hash, file)
	return fmt.Sprintf("%x", hash.Sum(nil)), err
}

func fileExists(filePath string) bool {
	_, err := os.Stat(filePath)
	return !os.IsNotExist(err)
}